
import { parentPort, workerData } from 'worker_threads';

import { KLineDTO } from '../kline-history/KLineHistory.entity';
import { FindTradingPoints, KlineWithVector } from '../../trader/FindTradingPoints';
import { Period, PeriodProcess } from '../../trader/PeriodProcess';
import { transformToCSV } from '../../utils';
import { CustomIndicators, MergeData } from '../../trader';
import { omit } from 'lodash';


export interface KlineSpreadVector extends MergeData, CustomIndicators {

}

let history: KLineDTO[] = [];
if (parentPort) {

  history = workerData.history
  // worker 中
  parentPort.on('message', async msg => {
    const result = await findTradingPoints(msg);
    parentPort.postMessage(result);
  });
} else {
  // 在 fork 
  process.on("message", async msg => {
    if (msg.type && msg.type === 'workerData') {
      history = msg.workerData.history
      return;
    }
    const result = await findTradingPoints(msg);
    // 将结果发送给主线程
    process.send(result);
  });
}
/**
 * 创建
 * @param {object} query
 * @param { Document }
 */
export const findTradingPoints = async function (data: { symbol: string; period: Period, target_profit: number }) {
  if (!history) {
    console.error(`findTradingPoints 缺少 workerData.history`)
  }
  const po = new FindTradingPoints(data.symbol, data.period as '15m' | '4h' | '1d', history);
  const tradingPoints = po.findTradingPoints(data.target_profit, data.period === '15m' ? 120 : undefined);
  const periodList = getPeriodList(data.period, po.feature_vector_list);
  return {
    tradingPoints,
    periodHistory: transformToCSV(periodList),
    periodList_15m: po.feature_vector_list
  }
}

function getPeriodList(period: Period, feature_vector_list: KlineWithVector[]) {
  if (period === '15m') {
    return feature_vector_list.map(({ feature_vector_detail, ...kline }) => {
      return Object.assign(kline, omit(feature_vector_detail, ['vector_stort_15m', 'vector_stort_4h', 'vector_stort_1d']))
    });
  }

  const periodProcess = new PeriodProcess<KlineWithVector>([period], 1);
  const periodList: KlineSpreadVector[] = [];
  periodProcess.onPeriod((period, kline) => {
    const feature_vector_detail = kline.feature_vector_detail
    delete kline.feature_vector_detail
    if (kline && feature_vector_detail) {
      periodList.push(Object.assign(kline, omit(feature_vector_detail, ['vector_stort_15m', 'vector_stort_4h', 'vector_stort_1d'])));
    }
  });

  feature_vector_list.forEach(data => {
    periodProcess.process(data.timestamp, (mergeData) => {

      mergeData.symbol = data.symbol;
      if (mergeData.open === undefined) {
        mergeData.open = data.open
      }
      mergeData.close = Number(data.close);
      mergeData.high = mergeData.high == undefined ? data.high : Math.max(mergeData.high, data.high);
      mergeData.low = mergeData.low == undefined ? data.low : Math.min(mergeData.low, data.low);
      mergeData.volume = mergeData.volume === undefined ? data.volume : mergeData.volume + data.volume;
      mergeData.feature_vector_detail = data.feature_vector_detail;

    });
  });
  return periodList;
}